package com.topcent.tioxyc.xxljob;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.topcent.tioxyc.constants.KeyConstant;
import com.topcent.tioxyc.mapper.Yy1KpiMapper;
import com.topcent.tioxyc.pojo.*;
import com.topcent.tioxyc.pojo.YY1_KPI;
import com.topcent.tioxyc.pojo.vo.*;
import com.topcent.tioxyc.util.ApiClient;
import com.topcent.tioxyc.util.ConnmeUtils;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.Header;
import org.apache.http.ParseException;
import org.apache.http.message.BasicHeader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.BinaryOperator;
import java.util.stream.Collectors;

/**
 * @author: 陈百万
 * @date: 2025/7/21 15:29
 * @Description: 销售45天出货统计逻辑定时器
 */
@Slf4j
@Component
public class CcSalesDataYearXxlJob {
    @Autowired
    private Yy1KpiMapper yy1KpiMapper;


    @XxlJob("salesDataYear")
    public void salesDataYear() {
        // 销售订单-交货数据分析计算
        salesDataOfAnalysis();
        // 销售订单-交货数据-来货检验状态
        salesDataOfInspectionAnalysis();
    }

    /**
     * 销售订单-交货数据分析计算
     */
    public void salesDataOfAnalysis() {
        Header[] headers = ConnmeUtils.createHeaders();
        String appId = "67f8aa2676b9b3942c49035f";
        // "formName": "销售订单-交货数据分析"
        String entryId = "686f26e10e96a68acbb7c879";

        // 获取检验通知单数据
        List<InspectionNoticeVO> inspectionNoticeList = getInspectionNoticeList();
        Map<String, Date> dateMap = processInspectionNoticeToDateMap(inspectionNoticeList);

        // 获取sap采购申请api数据
        Header[] sapHeaders = new Header[3];
        String auth = KeyConstant.sapSALE001APIName + ":" + KeyConstant.sapSALE001APIPass;
        String encodedAuth = Base64.getEncoder().encodeToString(auth.getBytes());
        String authHeader = "Basic " + encodedAuth;
        sapHeaders[0] = new BasicHeader("Accept", "application/json");
        sapHeaders[1] = new BasicHeader("Authorization", authHeader);
        sapHeaders[2] = new BasicHeader("x-csrf-token", "Fetch");
        JSONObject entries =
                ApiClient.sendGetRequest("https://my200654-api.s4hana.sapcloud.cn/sap/opu/odata/sap/YY1_PURREQUISITIONITEM_API_CDS/YY1_PurRequisitionItem_API", sapHeaders, null);
        String d = entries.getStr("d");
        JSONObject sapObjects = JSONUtil.parseObj(d);
        String results = sapObjects.getStr("results");
        JSONArray objectss = JSONUtil.parseArray(results);
        List<PurchaseRequisitionSAPVO> purchaseRequisitionSAPVOList = JSONUtil.toList(objectss, PurchaseRequisitionSAPVO.class);
        // 同时处理两个日期字段的赋值
        purchaseRequisitionSAPVOList.forEach(vo -> {
            // 处理创建日期
            vo.setCreationDate(parseSapDate(vo.getPurchaseReqnCreationDate()));
            // 处理审批日期
            vo.setReleaseDate(parseSapDate(vo.getPurchaseRequisitionReleaseDate()));
        });
        // 构建映射：(销售单号+销售行项目+物料号) → 对应的PurchaseRequisitionSAPVO对象
        Map<String, PurchaseRequisitionSAPVO> sapPurchaseRequisitionDataMap = purchaseRequisitionSAPVOList.stream()
                .collect(Collectors.toMap(
                        // 生成键：组合三个字段
                        vo -> generateKey(vo.getSDDocument(), vo.getSalesDocumentItem(), vo.getMaterial()),
                        // 值：直接使用当前对象
                        vo -> vo,
                        // 重复键处理：保留第一个出现的对象
                        (existing, replacement) -> existing
                ));

        // 获取用户人员信息
        Map<String ,Object> person =new HashMap<>();
        person.put("dept_no", 1);
        person.put("has_child", true);
        JSONObject personResult = ApiClient.sendPostRequest(KeyConstant.Jian_URL + "/v5/corp/department/user/list", headers, JSONUtil.toJsonStr(person));
        String personData = personResult.getStr("users");
        JSONArray personObjects = JSONUtil.parseArray(personData);
        List<Assignee> personList = JSONUtil.toList(personObjects, Assignee.class);

        // 获取销售部门信息
        Map<String ,Object> cond =new HashMap<>();
        cond.put("dept_no", 1);
        cond.put("has_child", true);
        JSONObject deptResult = ApiClient.sendPostRequest(KeyConstant.Jian_URL + "/v5/corp/department/list", headers, JSONUtil.toJsonStr(cond));
        String data = deptResult.getStr("departments");
        JSONArray objects = JSONUtil.parseArray(data);
        List<DepartmentVO> deptList = JSONUtil.toList(objects, DepartmentVO.class);

        //批量删除简道云数据
        selectAndList(headers, appId, entryId);

        Map<String, String> userNameMap = personList.stream()
                .collect(Collectors.toMap(Assignee::getName, Assignee::getUsername, (v1, v2) -> v1));

        Map<String, Integer> deptMap = deptList.stream()
                .collect(Collectors.toMap(DepartmentVO::getName, DepartmentVO::getDept_no, (v1, v2) -> v1));

        // 只调用一次耗时方法，缓存结果
        List<SalesOrder> salesOrderList = this.getSalesOrderList();

        // 获取最早审核日期
        Map<String, DateTime> salesDocMinDateMap = salesOrderList.stream()
                .filter(so -> so.getReview_date() != null) // 过滤空日期
                .collect(Collectors.toMap(
                        SalesOrder::get_widget_1718759603973, // 键：销售单号
                        SalesOrder::getReview_date,   // 值：日期
                        BinaryOperator.minBy(Comparator.naturalOrder()) // 冲突时保留较小的日期
                ));

        // 获取是否出库 true
        Map<String, String> salesDocLatestStockOutMap = salesOrderList.stream()
                .filter(so -> so.getCreateTime() != null)
                .collect(Collectors.toMap(
                        SalesOrder::get_widget_1718759603973,
                        so -> new AbstractMap.SimpleEntry<>(so.getCreateTime(), so.get_widget_1730952275092()),
                        // 先保留时间和值的映射，合并时比较时间
                        (entry1, entry2) -> entry1.getKey().isAfter(entry2.getKey()) ? entry1 : entry2
                ))
                // 最后提取值（是否出库存）
                .entrySet().stream()
                .collect(Collectors.toMap(
                        Map.Entry::getKey,
                        entry -> entry.getValue().getValue()
                ));


        //客户建档日期
        Map<String, Date> customerList = getCustomerList();

        //销售表数据
        List<com.topcent.tioxyc.pojo.YY1_KPI> yy1KpiList = yy1KpiMapper.selectAfterJune();
        // 定义需要排除的销售订单号
        List<String> excludeSales = Arrays.asList("2000000383",
                "2000005882",
                "2000006099",
                "2000006443",
                "2000006437",
                "2000006450",
                "2000006451",
                "2000006452",
                "2000006435");
        // 过滤掉这些订单号的数据（保留其他所有数据）
        yy1KpiList = yy1KpiList.stream()
                .filter(kpi -> !excludeSales.contains(kpi.getSalesDocument())) // 核心：排除目标订单号
                .collect(Collectors.toList()); // 返回可修改的ArrayList

        List<com.topcent.tioxyc.pojo.YY1_KPI> yy1KpiListNew = new ArrayList<>();

        String dateTime = "2025-06-01 00:00:00";
        DateTime DATE_THRESHOLD = new DateTime(dateTime);
        // 遍历销售数据列表
        for (com.topcent.tioxyc.pojo.YY1_KPI kpi : yy1KpiList) {
            String salesDocument = kpi.getSalesDocument(); // 获取销售订单号

            // 通过订单号获取最早审核时间
            DateTime minApprovalTime = salesDocMinDateMap.get(salesDocument);

            // 判断时间是否存在且大于等于2025年6月1日
            if (minApprovalTime != null && !minApprovalTime.isBefore(DATE_THRESHOLD)) {
                kpi.setYY1_lastapptime_SDHS(minApprovalTime); // 赋值给对象
                yy1KpiListNew.add(kpi);
            }
        }

        // 1. 先按销售单号分组（保留所有组的原始数据）
        Map<String, List<com.topcent.tioxyc.pojo.YY1_KPI>> groupBySalesDoc = yy1KpiListNew.stream()
                .filter(kpi -> kpi.getSalesDocument() != null && !kpi.getSalesDocument().trim().isEmpty())
                .collect(Collectors.groupingBy(com.topcent.tioxyc.pojo.YY1_KPI::getSalesDocument));

        // 2. 筛选出总和>5000的组，保留原始数据
        Map<String, List<com.topcent.tioxyc.pojo.YY1_KPI>> resultMap = new HashMap<>();

        for (Map.Entry<String, List<com.topcent.tioxyc.pojo.YY1_KPI>> entry : groupBySalesDoc.entrySet()) {
            String salesDoc = entry.getKey(); // 销售单号
            List<com.topcent.tioxyc.pojo.YY1_KPI> kpiList = entry.getValue(); // 该组的所有数据

            // 计算当前组的ConditionAmount总和
            BigDecimal total = kpiList.stream()
                    .map(kpi -> kpi.getConditionAmount() != null ? kpi.getConditionAmount() : BigDecimal.ZERO)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            // 筛选总和>5000的组
            if (total.compareTo(new BigDecimal("0")) > 0) {
                resultMap.put(salesDoc, kpiList); // 保留该组的原始数据
            }
        }
        // 获取交货表数据
        List<DeliveryDocumentsEntity> originalData = yy1KpiMapper.selecDeliveryDocumentsDatatAfterJune();

        // 获取采购订单原始数据
        List<PurchaseOrderList> originalProductData = yy1KpiMapper.selectPurchaseOrderAll();

        //构建交货单索引（用于快速匹配）
        Map<String, List<DeliveryDocumentsEntity>> deliveryIndex = originalData.stream()
                .filter(delivery -> delivery.getReferenceSDDocument() != null &&
                        delivery.getReferenceSDDocumentItem() != null)
                .collect(Collectors.groupingBy(
                        delivery -> delivery.getReferenceSDDocument() + "_" + delivery.getReferenceSDDocumentItem()
                ));

        // 采购订单
        // 构建映射：(销售单号+销售行项目+物料号) → 对应的PurchaseOrderList对象
        Map<String, PurchaseOrderList> productIndex = originalProductData.stream()
                .collect(Collectors.toMap(
                        // 生成键：组合三个字段
                        vo -> generateKey(vo.getSalesOrder(), vo.getSalesOrderItem(), vo.getMaterial()),
                        // 值：直接使用当前对象
                        vo -> vo,
                        // 重复键处理：保留第一个出现的对象
                        (existing, replacement) -> existing
                ));



        // 遍历每个销售单组，匹配交货状态
        for (List<com.topcent.tioxyc.pojo.YY1_KPI> kpiList : resultMap.values()) {
            // 统计组内状态
            int fullyDeliveredCount = 0;
            int partiallyDeliveredCount = 0;
            int notDeliveredCount = 0;
            Date latestDeliveryDate = null;

            // 遍历组内每条销售单行
            for (com.topcent.tioxyc.pojo.YY1_KPI kpi : kpiList) {
                String key = kpi.getSalesDocument() + "_" + kpi.getSalesDocumentItem();
                List<DeliveryDocumentsEntity> deliveries = deliveryIndex.getOrDefault(key, Collections.emptyList());
                // 交货数量
                int totalDeliveryQuantity = deliveries.stream()
                        .mapToInt(DeliveryDocumentsEntity::getActualDeliveryQuantity)
                        .sum();
                kpi.setDeliveryNum(totalDeliveryQuantity);
                kpi.setDeliveryNo(CollectionUtils.isEmpty(deliveries) ? null : deliveries.getFirst().getDeliveryDocument());

                if (deliveries.isEmpty()) {
                    // 未找到对应交货单
                    kpi.set_widget_1752125855356("未出货");
                    notDeliveredCount++;
                } else {
                    // 找到对应交货单，检查数量是否一致
                    int salesQuantity = kpi.getQuantity();


                    if (salesQuantity == totalDeliveryQuantity) {
                        // 数量完全匹配
                        kpi.set_widget_1752125855356("全部出货");
                        fullyDeliveredCount++;
                    } else {
                        // 数量不匹配
                        kpi.set_widget_1752125855356("部分出货");
                        partiallyDeliveredCount++;
                    }

                    // 查找最晚交货日期
                    Date currentLatestDate = deliveries.stream()
                            .map(DeliveryDocumentsEntity::getActualGoodsMovementDate)
                            .max(Date::compareTo)
                            .orElse(null);

                    if (currentLatestDate != null &&
                            (latestDeliveryDate == null || currentLatestDate.after(latestDeliveryDate))) {
                        latestDeliveryDate = currentLatestDate;
                    }
                }
            }
            // 设置组整体交货状态
            String groupStatus;
            if (fullyDeliveredCount == kpiList.size()) {
                groupStatus = "全部出货";
            } else if (notDeliveredCount == kpiList.size()) {
                groupStatus = "未出货";
            } else {
                groupStatus = "部分出货";
            }

            // 为组内每条记录设置整体状态和最晚交货日期
            for (com.topcent.tioxyc.pojo.YY1_KPI kpi : kpiList) {
                kpi.set_widget_1752125855357(groupStatus);
                kpi.set_widget_1752128631870(latestDeliveryDate);
            }
        }

        List<Map<String, Object>> mapList = new ArrayList<>();
        // 遍历resultMap中的所有KPI记录（已处理过交货状态）
        for (List<com.topcent.tioxyc.pojo.YY1_KPI> kpiList : resultMap.values()) {
            for (YY1_KPI yy1Kpi : kpiList) {
                SalesDataAnalysis vo = new SalesDataAnalysis();
                //采购申请信息
                PurchaseRequisitionSAPVO purchaseRequisitionSAPVO = sapPurchaseRequisitionDataMap.get(
                        generateKey(yy1Kpi.getSalesDocument(), yy1Kpi.getSalesDocumentItem(), yy1Kpi.getMaterial()));
                if(ObjectUtils.isNotEmpty(purchaseRequisitionSAPVO)){
                    // 设置字段值
                    vo.set_widget_1753423798924(purchaseRequisitionSAPVO.getRequestedQuantity());
                    vo.set_widget_1753423798925(purchaseRequisitionSAPVO.getCreationDate());
                    vo.set_widget_1753423798926(purchaseRequisitionSAPVO.getReleaseDate());
                }
                vo.set_widget_1753423798927(yy1Kpi.getYY1_Brand_SDI() ? "是" : "否");

                // 采购订单
                PurchaseOrderList purchaseOrderList = productIndex.get(
                        generateKey(yy1Kpi.getSalesDocument(), yy1Kpi.getSalesDocumentItem(), yy1Kpi.getMaterial()));

                if(ObjectUtils.isNotEmpty(purchaseOrderList)){
                    // 设置字段值
                    // 采购订单日期
                    vo.set_widget_1756707938600(parseDate(purchaseOrderList.getPurchaseOrderDate()));
                    // 采购订单数量
                    vo.set_widget_1756707938601(Integer.valueOf(purchaseOrderList.getOrderQuantity()));
                }

                // 供方完工日期
                vo.set_widget_1753750960203(dateMap.get(generateKey(yy1Kpi.getSalesDocument(), yy1Kpi.getSalesDocumentItem(), yy1Kpi.getMaterial())));

                vo.set_widget_1743998205163(getYearMonth(yy1Kpi.getYY1_lastapptime_SDH()));
                vo.set_widget_1743997558327(yy1Kpi.getSalesDocument());
                vo.set_widget_1744784769246(yy1Kpi.getSalesDocument());
                vo.set_widget_1743997558328(yy1Kpi.getSalesDocumentItem());
                vo.set_widget_1743997558329(yy1Kpi.getSoldToParty());
                vo.set_widget_1743997558330(yy1Kpi.getCustomerName());
                vo.set_widget_1743997558331(yy1Kpi.getBusinessPartnerName1());
                vo.set_widget_1744099905120(yy1Kpi.getAuthorizationGroupText());
                vo.set_widget_1751677806926(yy1Kpi.getAuthorizationGroupText());
                vo.set_widget_1743997558333(yy1Kpi.getCompanyCodeName());
                vo.set_widget_1743997558335(yy1Kpi.getPurchaseOrderByCustomer());
                vo.set_widget_1743997558336(yy1Kpi.getMaterial());
                vo.set_widget_1743997558337(yy1Kpi.getSalesDocumentItemText());
                vo.set_widget_1743997558338(yy1Kpi.getQuantity());
                vo.set_widget_1743997558339(yy1Kpi.getNetAmount());
                vo.set_widget_1743997558340(yy1Kpi.getOrderQuantityUnit());
                vo.set_widget_1743997558341(yy1Kpi.getConditionAmount());
                vo.set_widget_1743997558342(yy1Kpi.getExchangeRate_a());
                vo.set_widget_1743997558343(yy1Kpi.getGroupCurrency());
                vo.set_widget_1743997558344(convertToISO8601Format(yy1Kpi.getYY1_lachangedatetime1_SDH()));
                vo.set_widget_1743997558345(yy1Kpi.getID());
                vo.set_widget_1743997558346(yy1Kpi.getSalesDocApprovalStatusDesc());
                vo.set_widget_1743997558347(yy1Kpi.getAddressSearchTerm2());
                vo.set_widget_1743997558348(convertToISO8601Format(yy1Kpi.getCreationDate()));
                vo.set_widget_1743997558349(yy1Kpi.getOverallTotalDeliveryStatus());
                vo.set_widget_1743997558350(yy1Kpi.getOverallDeliveryStatus());
                vo.set_widget_1743997558351(yy1Kpi.getPlant());
                vo.set_widget_1743997558352(yy1Kpi.getCurrency());
                vo.set_widget_1743997558353(yy1Kpi.getExchangeRate_b());
                vo.set_widget_1743997558354(yy1Kpi.getNetAmount_1());
                vo.set_widget_1743997558355(yy1Kpi.getConditionAmount1());
                vo.set_widget_1743997558356(yy1Kpi.getConditionCurrency());

                vo.set_widget_1743997558357(yy1Kpi.getGsjing());
                vo.set_widget_1743997558358(yy1Kpi.getGshan());
                vo.set_widget_1743997558359(convertToISO8601Format(yy1Kpi.getYY1_lastapptime_SDH()));
                vo.set_widget_1743997558360(yy1Kpi.getYY1_ZBMCL_SD_SDI());
                vo.set_widget_1743997558361(yy1Kpi.getYY1_ZCL_SD_SDI());
                vo.set_widget_1743997558362(yy1Kpi.getYY1_ZGGCC_SD_SDI());
                vo.set_widget_1743997558363(yy1Kpi.getYY1_ZBZXX_SD_SDI());
                vo.set_widget_1743997558364(yy1Kpi.getYY1_KS_SD_SDI());
                vo.set_widget_1743997558365(yy1Kpi.getYY1_ZCPJZ_SD_SDI());
                vo.set_widget_1743997558366(yy1Kpi.getYY1_ZPJ_SD_SDI());
                vo.set_widget_1743997558367(yy1Kpi.getVCDescription());
                vo.set_widget_1743997558368(yy1Kpi.getYY1_BGPM_PRD());
                vo.set_widget_1743997558369(yy1Kpi.getYY1_Brand_SDI());
                vo.set_widget_1743997558370(yy1Kpi.getCountryName());
                vo.set_widget_1743997558371(yy1Kpi.getYY1_khly_bus());
                vo.set_widget_1743997558372(yy1Kpi.getBusinessPartnerGroupingText());
                vo.set_widget_1743997558373(convertToISO8601Format(yy1Kpi.getRequestedDeliveryDate()));

                vo.set_widget_1749538106589(yy1Kpi.getYY1_lastapptime_SDHS());// 最早审核时间
                vo.set_widget_1749628279931(customerList.get(yy1Kpi.getSoldToParty()));//客户建档日期

                if(StringUtils.isNotBlank(yy1Kpi.getSalesOfficeName()) && yy1Kpi.getSalesOfficeName().contains("中非销售")){
                    yy1Kpi.setSalesOfficeName("BCP中非销售部");
                }else if(StringUtils.isNotBlank(yy1Kpi.getSalesOfficeName()) && yy1Kpi.getSalesOfficeName().contains("东南亚销售")){
                    yy1Kpi.setSalesOfficeName("BCP东南亚销售部");
                }else if(StringUtils.isNotBlank(yy1Kpi.getSalesOfficeName()) && yy1Kpi.getSalesOfficeName().contains("DIY销售部")){
                    yy1Kpi.setSalesOfficeName("BCP美澳销售部");
                }else if(StringUtils.isNotBlank(yy1Kpi.getSalesOfficeName()) && yy1Kpi.getSalesOfficeName().contains("PRO国内销售部")){
                    yy1Kpi.setSalesOfficeName("PRO亚非销售部");
                }

                vo.set_widget_1752125855356(yy1Kpi.get_widget_1752125855356());
                vo.set_widget_1752125855357(yy1Kpi.get_widget_1752125855357());
                vo.set_widget_1752128631870(yy1Kpi.get_widget_1752128631870());
                vo.set_widget_1752128631871(yy1Kpi.getDeliveryNum());
                vo.set_widget_1752128631872(countTime(vo.get_widget_1752128631870(), vo.get_widget_1749538106589()));
                vo.set_widget_1752560851698(yy1Kpi.getDeliveryNo());

                String sName = yy1Kpi.getSalesOfficeName();
                vo.set_widget_1751677806927(sName);

                String username = userNameMap.get(vo.get_widget_1744099905120());
                if(("刘晓琪").equals(vo.get_widget_1744099905120())){
                    username = "woxjrqDwAAUDe1Gd9cSVXI5sfRaqZ9jQ";
                }
                if (username != null) {
                    vo.set_widget_1744099905120(username);
                }

                Integer deptNo = deptMap.get(sName);
                if (deptNo != null) {
                    vo.set_widget_1744094850882(deptNo);
                }

                vo.set_widget_1753265368863("true".equals(salesDocLatestStockOutMap.get(yy1Kpi.getSalesDocument())) ? "是" : "否");

                vo.set_id(null);
                mapList.add(ConnmeUtils.convertEntityToMap(vo));
            }
        }
        log.info("销售订单数据mapList：==== {}", mapList.size());
        // 批量存入简道云
        ConnmeUtils.batchAddList(headers, appId, entryId, mapList);
        System.out.println("数据插入成功：" + mapList.size());
    }

    public String countTime(Date a, Date b) {
        if (a == null || b == null) {
            return "";
        }

        // +8 小时偏移
        DateTime d1 = DateUtil.offsetHour(DateUtil.date(a), 8);
        DateTime d2 = DateUtil.offsetHour(DateUtil.date(b), 8);

        long days = DateUtil.between(d1, d2, DateUnit.DAY);
        if(d1.isBefore(d2) && days > 0){
            return "-" + days;
        }
        return String.valueOf(days);
    }

    /**
     * 销售订单-交货数据-来货检验状态
     */
    public void salesDataOfInspectionAnalysis() {
        Header[] headers = ConnmeUtils.createHeaders();

        // 1. 获取三种表单数据
        List<InspectedVO> salesDataList = fetchJianDaoYunData(
                headers, "67f8aa2676b9b3942c49035f", "686f26e10e96a68acbb7c879", InspectedVO.class
        );

        List<ZPurchaseOrderList> purchaseDataList = fetchJianDaoYunData(
                headers, "67f8aa2676b9b3942c49035f", "67ff675568c6ea7be7efebe9", ZPurchaseOrderList.class
        );

        List<InspectionData> inspectionDataList = fetchJianDaoYunData(
                headers, "64a7b7416bbd930007630ed5", "64a7b81afc35ba00082dbcad", InspectionData.class
        );

        // 2. 构建采购订单索引（销售订单号+行号+物料号 → 采购单信息）
        Map<String, ZPurchaseOrderList> purchaseIndex = purchaseDataList.stream()
                .collect(Collectors.toMap(
                        po -> generateKey(po.get_widget_1744791381554(), po.get_widget_1744791381555(), po.get_widget_1744791381526()),
                        po -> po,
                        (existing, replacement) -> existing // 重复键处理：保留第一个
                ));

        // 3. 构建检验结果索引（采购单号+行号+物料号 → 检验结果）
        Map<String, InspectionData> inspectionIndex = inspectionDataList.stream()
                .collect(Collectors.toMap(
                        insp -> generateKey(insp.getPurchasing_no(), padWithZeros(insp.getPurchasing_hang()), insp.getItem_no()),
                        insp -> insp,
                        (existing, replacement) -> existing // 重复键处理：保留第一个
                ));

        // 4. 处理销售订单数据
        for (InspectedVO salesData : salesDataList) {
            // 按销售订单号+行号分组销售订单行
            Map<String, List<InspectedVO>> salesLinesByOrder = salesDataList.stream()
                    .filter(line -> line.get_widget_1743997558327().equals(salesData.get_widget_1743997558327()))
                    .collect(Collectors.groupingBy(InspectedVO::get_widget_1743997558327));

            // 处理每个销售订单行
            for (Map.Entry<String, List<InspectedVO>> entry : salesLinesByOrder.entrySet()) {
                String salesLineNo = entry.getKey();
                List<InspectedVO> lines = entry.getValue();

                for (InspectedVO line : lines) {
                    // 生成销售订单行的唯一键
                    String salesKey = generateKey(
                            line.get_widget_1743997558327(),
                            line.get_widget_1743997558328(),
                            line.get_widget_1743997558336()
                    );

                    // 获取对应的采购订单信息
                    ZPurchaseOrderList purchaseOrder = purchaseIndex.get(salesKey);

                    if (purchaseOrder != null) {
                        // 生成采购订单的唯一键
                        String purchaseKey = generateKey(
                                purchaseOrder.get_widget_1744791381513(),
                                purchaseOrder.get_widget_1744791381514(),
                                purchaseOrder.get_widget_1744791381526()
                        );

                        // 获取对应的检验结果
                        InspectionData inspectionData = inspectionIndex.get(purchaseKey);

                        if (inspectionData != null) {
                            // 设置行检验状态
                            String inspectionResult = inspectionData.getInspection_result();
                            line.set_widget_1752480273251("NG".equals(inspectionResult) ? "未检验" : "已检验");

                            // 设置行最后检验时间
                            if (line.get_widget_1752480273251().equals("已检验")) {
                                line.set_widget_1752480273253(parseDate(inspectionData.getDate_of_inspection()));
                            }
                        } else {
                            // 没有找到检验结果
                            line.set_widget_1752480273251("未检验");
                        }
                    } else {
                        // 没有找到对应的采购订单
                        line.set_widget_1752480273251("未检验");
                    }
                }
            }

            // 5. 计算销售订单整体检验状态
            calculateOverallStatus(salesData, salesLinesByOrder);

            Map<String, Object> parameterInster = new HashMap<>();
            parameterInster.put("app_id", "67f8aa2676b9b3942c49035f");
            parameterInster.put("entry_id", "686f26e10e96a68acbb7c879");
            parameterInster.put("is_start_trigger", "true");
            parameterInster.put("data_id", salesData.get_id());
            salesData.set_id(null);
            parameterInster.put("data", ConnmeUtils.convertEntityToMapNull(salesData));
            String jsonSalee = JSONUtil.toJsonStr(parameterInster);
            ApiClient.sendPostRequest(KeyConstant.Jian_URL + "/v5/app/entry/data/update", headers, jsonSalee);
        }

        log.info("处理完成，共{}条销售订单数据", salesDataList.size());
    }

    /**
     * 生成复合键（用于Map索引）
     */
    private String generateKey(String... parts) {
        return String.join("|", parts);
    }

    /**
     * 解析检验日期字符串为Date对象
     */
    private Date parseDate(String dateStr) {
        if (dateStr == null || dateStr.isEmpty()) {
            return null;
        }
        // 根据实际日期格式调整解析逻辑
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            return sdf.parse(dateStr);
        } catch (ParseException e) {
            log.error("日期解析失败: {}", dateStr, e);
            return null;
        } catch (java.text.ParseException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 计算销售订单整体检验状态
     */
    private void calculateOverallStatus(InspectedVO salesData,
                                        Map<String, List<InspectedVO>> salesLinesByOrder) {
        // 获取该销售订单下所有行的检验状态
        List<String> allLineStatus = salesLinesByOrder.values().stream()
                .flatMap(List::stream)
                .map(InspectedVO::get_widget_1752480273251)
                .toList();

        // 计算整体状态
        long uninspectedCount = allLineStatus.stream().filter("未检验"::equals).count();
        long inspectedCount = allLineStatus.stream().filter("已检验"::equals).count();

        if (uninspectedCount == allLineStatus.size()) {
            salesData.set_widget_1752480273252("未检验");
            salesData.set_widget_1752480273254(null); // 全未检验，无检验时间
        } else if (inspectedCount == allLineStatus.size()) {
            salesData.set_widget_1752480273252("已检验");
            // 获取所有行的最晚检验时间
            Date latestInspectionDate = salesLinesByOrder.values().stream()
                    .flatMap(List::stream)
                    .map(InspectedVO::get_widget_1752480273253)
                    .filter(Objects::nonNull)
                    .max(Date::compareTo)
                    .orElse(null);
            salesData.set_widget_1752480273254(latestInspectionDate);
        } else {
            salesData.set_widget_1752480273252("部分检验");
            // 获取已检验行中的最晚检验时间
            Date latestInspectionDate = salesLinesByOrder.values().stream()
                    .flatMap(List::stream)
                    .filter(line -> "已检验".equals(line.get_widget_1752480273251()))
                    .map(InspectedVO::get_widget_1752480273253)
                    .filter(Objects::nonNull)
                    .max(Date::compareTo)
                    .orElse(null);
            salesData.set_widget_1752480273254(latestInspectionDate);
        }
    }

    /**
     * 通用方法：从简道云分页获取表单数据
     * @param headers 请求头
     * @param appId 应用ID
     * @param entryId 表单ID
     * @param clazz 实体类Class（用于JSON转换）
     * @return 转换后的实体类列表
     * @param <T> 泛型：适配不同实体类（SalesDataAnalysis/ZPurchaseOrderList等）
     */
    private <T> List<T> fetchJianDaoYunData(Header[] headers, String appId, String entryId, Class<T> clazz) {
        List<T> resultList = new ArrayList<>();
        Map<String, Object> params = new HashMap<>();
        params.put("app_id", appId);
        params.put("entry_id", entryId);
        boolean hasMore = true;
        String lastDataId = ""; // 分页标记：上一页最后一条数据的ID

        do {
            // 设置分页参数（首次请求无data_id，后续请求携带上一页最后一条ID）
            if (!lastDataId.isEmpty()) {
                params.put("data_id", lastDataId);
            }
            params.put("limit", 100); // 每页100条

            // 调用简道云API
            String jsonParams = JSONUtil.toJsonStr(params);
            JSONObject response = ApiClient.sendPostRequest(
                    KeyConstant.Jian_URL + "/v5/app/entry/data/list",
                    headers,
                    jsonParams
            );

            // 解析数据并转换为实体类
            String dataJson = response.getStr("data");
            JSONArray dataArray = JSONUtil.parseArray(dataJson);
            List<T> pageData = JSONUtil.toList(dataArray, clazz);

            // 更新分页状态（是否还有下一页）
            if (pageData.size() == 100) {
                // 取当前页最后一条数据的ID，作为下一页的查询起点
                // 假设实体类有get_id()方法（简道云数据通常有_id字段）
                T lastData = pageData.get(pageData.size() - 1);
                lastDataId = getLastDataId(lastData); // 反射获取_id字段值
            } else {
                hasMore = false; // 不足100条，无下一页
            }

            // 累加数据
            resultList.addAll(pageData);
            System.out.println("数组大小："+ resultList.size());
        } while (hasMore);

        return resultList;
    }

    /**
     * 反射获取实体类的_id字段值（简道云数据默认有_id作为唯一标识）
     */
    private <T> String getLastDataId(T data) {
        try {
            // 假设实体类有get_id()方法
            Method method = data.getClass().getMethod("get_id");
            return (String) method.invoke(data);
        } catch (Exception e) {
            // 异常处理：若没有_id字段，返回空（终止分页）
            return "";
        }
    }

    /**
     * 将数字字符串补零至5位（如"10"→"00010"，"123"→"00123"）
     * @param numStr 原始数字字符串（如"10"、"20"）
     * @return 补零后的5位字符串
     */
    private String padWithZeros(String numStr) {
        if (numStr == null || numStr.trim().isEmpty()) {
            return "00000"; // 空值默认返回5个0（根据业务调整）
        }
        // 去除可能的空格，转换为数字后再格式化
        try {
            int num = Integer.parseInt(numStr.trim());
            // 格式化：%05d 表示5位数字，不足补0
            return String.format("%05d", num);
        } catch (NumberFormatException e) {
            // 非数字情况：返回原始值（或根据业务处理）
            //log.warn("采购行号不是数字：{}", numStr);
            return numStr;
        }
    }

    /**
     * 将数字字符串补零至6位（如"10"→"000010"，"123"→"000123"）
     * @param numStr 原始数字字符串（如"10"、"20"）
     * @return 补零后的6位字符串
     */
    private String padWithZeros6(String numStr) {
        if (numStr == null || numStr.trim().isEmpty()) {
            return "000000"; // 空值默认返回6个0（根据业务调整）
        }
        // 去除可能的空格，转换为数字后再格式化
        try {
            int num = Integer.parseInt(numStr.trim());
            // 格式化：%06d 表示6位数字，不足补0
            return String.format("%06d", num);
        } catch (NumberFormatException e) {
            // 非数字情况：返回原始值（或根据业务处理）
            //log.warn("采购行号不是数字：{}", numStr);
            return numStr;
        }
    }


    public void selectAndList(Header[] headers,String appId,String entryId){
        // 获取到销售订单数据-YY1_KPI数据。
        List<Lin> consolidatedOrderVOList = new ArrayList<>();
        Map<String, Object> parameter = new HashMap<>();
        parameter.put("app_id", appId);
        parameter.put("entry_id", entryId);

        Map<String, Object> filter = new HashMap<>();
        filter.put("rel", "and");
        Map<String, Object> cond = new HashMap<>();
        cond.put("field", "_widget_1744599627176");
        cond.put("type", "text");
        cond.put("method", "empty");
        List<Map<String, Object>> conds = new ArrayList<>();
        conds.add(cond);
        filter.put("cond", conds);
        parameter.put("filter", filter);

        boolean fale = true;
        String zh = "";
        do {
            if (!zh.isEmpty()) {
                parameter.put("data_id", zh);
            }
            parameter.put("limit", 100);
            String jsonSale = JSONUtil.toJsonStr(parameter);
            JSONObject jdySale = ApiClient.sendPostRequest(KeyConstant.Jian_URL + "/v5/app/entry/data/list", headers, jsonSale);
            String data = jdySale.getStr("data");
            JSONArray objects = JSONUtil.parseArray(data);
            List<Lin> list = JSONUtil.toList(objects, Lin.class);
            if (list.size() == 100) {
                zh = list.getLast().get_id();
            } else {
                fale = false;
            }
            consolidatedOrderVOList.addAll(list);
        } while (fale);
        log.info("销售订单数据-YY1_KPI表单数据size：" + consolidatedOrderVOList.size());
        // 判断集合是否有值 有则删除 一次只能删除100条
        if (CollectionUtils.isNotEmpty(consolidatedOrderVOList)) {
            // 提取所有数据ID
            List<String> dataIds = consolidatedOrderVOList.stream()
                    .map(Lin::get_id) // get_id() 是获取数据ID的方法
                    .collect(Collectors.toList());

            int batchSize = 100;
            for (int i = 0; i < dataIds.size(); i += batchSize) {
                int endIndex = Math.min(i + batchSize, dataIds.size());
                List<String> batchDataIds = dataIds.subList(i, endIndex);

                // 构造删除接口请求参数
                Map<String, Object> deleteParam = new HashMap<>();
                deleteParam.put("app_id", appId);
                deleteParam.put("entry_id", entryId);
                deleteParam.put("data_ids", batchDataIds);

                // 发送删除请求
                String jsonDelete = JSONUtil.toJsonStr(deleteParam);
                JSONObject deleteResponse = ApiClient.sendPostRequest(KeyConstant.Jian_URL + "/v5/app/entry/data/batch_delete", headers, jsonDelete);
                // 记录响应日志,判断删除是否成功
                log.info("删除接口响应：{}", deleteResponse);
            }
        }
    }

    // 时间Z转化
    public static String convertToISO8601Format(String dbTime) {
        if(StringUtils.isEmpty(dbTime)){
            return "";
        }
        // 查找秒后的小数部分
        int dotIndex = dbTime.indexOf(".");

        if (dotIndex != -1) {
            // 如果有小数部分，去掉并加上 ".000"
            dbTime = dbTime.substring(0, dotIndex) + ".000";
        } else {
            // 如果没有小数部分，直接加 ".000"
            dbTime = dbTime + ".000";
        }
        // 定义数据库时间格式
        DateTimeFormatter dbFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");

        // 解析数据库时间
        LocalDateTime localDateTime = LocalDateTime.parse(dbTime, dbFormatter);

        // 将时间减去 8 小时
        LocalDateTime result = localDateTime.minusHours(8);

        // 将结果转换为字符串输出
        return result.format(dbFormatter);
    }

    // 取年月
    public static String getYearMonth(String dbTime) {
        if (dbTime == null || dbTime.isEmpty()) {
            return null;
        }
        // 查找秒后的小数部分
        int dotIndex = dbTime.indexOf(".");

        if (dotIndex != -1) {
            // 如果有小数部分，去掉并加上 ".000"
            dbTime = dbTime.substring(0, dotIndex) + ".000";
        } else {
            // 如果没有小数部分，直接加 ".000"
            dbTime = dbTime + ".000";
        }

        // 定义数据库时间格式
        DateTimeFormatter dbFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
        LocalDateTime localDateTime = LocalDateTime.parse(dbTime, dbFormatter);

        // 将时间减去 8 小时
        LocalDateTime result = localDateTime.minusHours(8);

        // 获取年份和月份
        return result.format(DateTimeFormatter.ofPattern("yyyy-MM"));
    }

    public Map<String, Date> getCustomerList(){
        Map<String, Date> customerMap = new HashMap<>();
        List<Customer> customerList = new ArrayList<>();
        Header[] headers = ConnmeUtils.createHeaders();
        Map<String, Object> parameter = new HashMap<>();
        parameter.put("app_id", "66a6f42ff97af74b02d217df");
        parameter.put("entry_id", "66a6f443333584e2c128154f");
        boolean fale = true;
        String zh = "";
        do {
            if (!zh.isEmpty()) {
                parameter.put("data_id", zh);
            }
            parameter.put("limit", 100);
            String jsonSale = JSONUtil.toJsonStr(parameter);
            JSONObject jdySale = ApiClient.sendPostRequest(KeyConstant.Jian_URL + "/v5/app/entry/data/list", headers, jsonSale);
            String data = jdySale.getStr("data");
            JSONArray objects = JSONUtil.parseArray(data);
            List<Customer> list = JSONUtil.toList(objects, Customer.class);
            if (list.size() == 100) {
                zh = list.getLast().get_id();
            } else {
                fale = false;
            }
            customerList.addAll(list);
        } while (fale);

        // 转换 List<Customer> 为 Map<String, Date>
        for (Customer customer : customerList) {
            String customerCode = customer.get_widget_1722305048887();
            Date createDate = customer.get_widget_1733204191654();

            // 处理空值（跳过无效数据）
            if (customerCode != null && createDate != null) {
                customerMap.put(customerCode, createDate);
            }
        }
        return customerMap;
    }

    public List<SalesOrder> getSalesOrderList(){
        List<SalesOrder> salesOrderList = new ArrayList<>();
        Header[] headers = ConnmeUtils.createHeaders();
        Map<String, Object> parameter = new HashMap<>();
        parameter.put("app_id", "667230ad22a8581756b77d52");
        parameter.put("entry_id", "667230b322a8581756b78353");

        Map<String, Object> filter = new HashMap<>();
        filter.put("rel", "and");
        Map<String, Object> cond = new HashMap<>();
        cond.put("field", "flowState");
        cond.put("type", "flowstate");
        cond.put("method", "eq");
        List<Integer> values = new ArrayList<>();
        values.add(1);
        cond.put("value", values);
        List<Map<String, Object>> conds = new ArrayList<>();
        conds.add(cond);
        filter.put("cond", conds);
        parameter.put("filter", filter);

        boolean fale = true;
        String zh = "";
        do {
            if (!zh.isEmpty()) {
                parameter.put("data_id", zh);
            }
            parameter.put("limit", 100);
            String jsonSale = JSONUtil.toJsonStr(parameter);
            JSONObject jdySale = ApiClient.sendPostRequest(KeyConstant.Jian_URL + "/v5/app/entry/data/list", headers, jsonSale);
            String data = jdySale.getStr("data");
            JSONArray objects = JSONUtil.parseArray(data);
            List<SalesOrder> list = JSONUtil.toList(objects, SalesOrder.class);
            if (list.size() == 100) {
                zh = list.getLast().get_id();
            } else {
                fale = false;
            }
            salesOrderList.addAll(list);
        } while (fale);
        return salesOrderList;
    }

    private DateTime parseSapDate(String sapDateStr) {
        if (StringUtils.isNotBlank(sapDateStr)) {
            long timestamp = Long.parseLong(ConnmeUtils.extractTimestamp(sapDateStr));
            LocalDateTime ldt = ConnmeUtils.convertTimestampToLocalDateTime(timestamp);
            return new DateTime(ConnmeUtils.formatDateTime(ldt), DatePattern.NORM_DATETIME_FORMAT);
        }
        return null;
    }

    // 获取检验通知单数据
    public List<InspectionNoticeVO> getInspectionNoticeList(){
        List<InspectionNoticeVO> inspectionNoticeVOList = new ArrayList<>();
        Header[] headers = ConnmeUtils.createHeaders();
        Map<String, Object> parameter = new HashMap<>();
        parameter.put("app_id", "6690c7633df0f4b90b4ef551");
        parameter.put("entry_id", "66a734001584068c255b2fb2");

        Map<String, Object> filter = new HashMap<>();
        filter.put("rel", "and");
        Map<String, Object> cond = new HashMap<>();
        cond.put("field", "flowState");
        cond.put("type", "flowstate");
        cond.put("method", "eq");
        List<Integer> values = new ArrayList<>();
        values.add(1);
        cond.put("value", values);
        List<Map<String, Object>> conds = new ArrayList<>();
        conds.add(cond);
        filter.put("cond", conds);
        parameter.put("filter", filter);

        boolean fale = true;
        String zh = "";
        do {
            if (!zh.isEmpty()) {
                parameter.put("data_id", zh);
            }
            parameter.put("limit", 100);
            String jsonSale = JSONUtil.toJsonStr(parameter);
            JSONObject jdySale = ApiClient.sendPostRequest(KeyConstant.Jian_URL + "/v5/app/entry/data/list", headers, jsonSale);
            String data = jdySale.getStr("data");
            JSONArray objects = JSONUtil.parseArray(data);
            List<InspectionNoticeVO> list = JSONUtil.toList(objects, InspectionNoticeVO.class);
            if (list.size() == 100) {
                zh = list.getLast().get_id();
            } else {
                fale = false;
            }
            inspectionNoticeVOList.addAll(list);
        } while (fale);
        return inspectionNoticeVOList;
    }



    public Map<String, Date> processInspectionNoticeToDateMap(List<InspectionNoticeVO> inspectionNoticeList) {
        // 构建结果映射：键为销售单号|销售单行号|产品编码，值为供方完工日期
        Map<String, Date> resultMap = new HashMap<>();

        for (InspectionNoticeVO noticeVO : inspectionNoticeList) {
            // 获取回仓产品明细列表
            List<InspectionNoticeVO.productDetail> productDetails = noticeVO.get_widget_1694481242685();
            if (productDetails == null || productDetails.isEmpty()) {
                continue; // 跳过无明细的数据
            }

            // 获取当前通知单的供方完工日期（所有明细共享同一日期）
            Date supplyFinishDate = noticeVO.get_widget_1753082933013();

            // 遍历明细，构建映射关系
            for (InspectionNoticeVO.productDetail detail : productDetails) {
                // 提取三个关键字段
                String salesOrderNo = detail.get_widget_1727059443400();
                String salesOrderLineNo = detail.get_widget_1727059443401();
                String productCode = detail.get_widget_1694481242687();

                // 跳过关键字段为空的数据（避免生成无效键）
                if (salesOrderNo == null || salesOrderLineNo == null || productCode == null) {
                    continue;
                }

                // 生成唯一键（销售单号|销售单行号|产品编码）
                String key = String.join("|", salesOrderNo, padWithZeros6(salesOrderLineNo), productCode);

                // 若键已存在，保留先出现的日期（如需保留最新日期，可改为 supplyFinishDate 覆盖）
                resultMap.putIfAbsent(key, supplyFinishDate);
            }
        }

        return resultMap;
    }
}
